if ("undefined" == typeof net) {
  var net = {}
}
if (!net.brehaut) {
  net.brehaut = {}
} (function() {
  "use strict";
  var css_colors = {
      aliceblue: '#F0F8FF',
      antiquewhite: '#FAEBD7',
      aqua: '#00FFFF',
      aquamarine: '#7FFFD4',
      azure: '#F0FFFF',
      beige: '#F5F5DC',
      bisque: '#FFE4C4',
      black: '#000000',
      blanchedalmond: '#FFEBCD',
      blue: '#0000FF',
      blueviolet: '#8A2BE2',
      brown: '#A52A2A',
      burlywood: '#DEB887',
      cadetblue: '#5F9EA0',
      chartreuse: '#7FFF00',
      chocolate: '#D2691E',
      coral: '#FF7F50',
      cornflowerblue: '#6495ED',
      cornsilk: '#FFF8DC',
      crimson: '#DC143C',
      cyan: '#00FFFF',
      darkblue: '#00008B',
      darkcyan: '#008B8B',
      darkgoldenrod: '#B8860B',
      darkgray: '#A9A9A9',
      darkgrey: '#A9A9A9',
      darkgreen: '#006400',
      darkkhaki: '#BDB76B',
      darkmagenta: '#8B008B',
      darkolivegreen: '#556B2F',
      darkorange: '#FF8C00',
      darkorchid: '#9932CC',
      darkred: '#8B0000',
      darksalmon: '#E9967A',
      darkseagreen: '#8FBC8F',
      darkslateblue: '#483D8B',
      darkslategray: '#2F4F4F',
      darkslategrey: '#2F4F4F',
      darkturquoise: '#00CED1',
      darkviolet: '#9400D3',
      deeppink: '#FF1493',
      deepskyblue: '#00BFFF',
      dimgray: '#696969',
      dimgrey: '#696969',
      dodgerblue: '#1E90FF',
      firebrick: '#B22222',
      floralwhite: '#FFFAF0',
      forestgreen: '#228B22',
      fuchsia: '#FF00FF',
      gainsboro: '#DCDCDC',
      ghostwhite: '#F8F8FF',
      gold: '#FFD700',
      goldenrod: '#DAA520',
      gray: '#808080',
      grey: '#808080',
      green: '#008000',
      greenyellow: '#ADFF2F',
      honeydew: '#F0FFF0',
      hotpink: '#FF69B4',
      indianred: '#CD5C5C',
      indigo: '#4B0082',
      ivory: '#FFFFF0',
      khaki: '#F0E68C',
      lavender: '#E6E6FA',
      lavenderblush: '#FFF0F5',
      lawngreen: '#7CFC00',
      lemonchiffon: '#FFFACD',
      lightblue: '#ADD8E6',
      lightcoral: '#F08080',
      lightcyan: '#E0FFFF',
      lightgoldenrodyellow: '#FAFAD2',
      lightgray: '#D3D3D3',
      lightgrey: '#D3D3D3',
      lightgreen: '#90EE90',
      lightpink: '#FFB6C1',
      lightsalmon: '#FFA07A',
      lightseagreen: '#20B2AA',
      lightskyblue: '#87CEFA',
      lightslategray: '#778899',
      lightslategrey: '#778899',
      lightsteelblue: '#B0C4DE',
      lightyellow: '#FFFFE0',
      lime: '#00FF00',
      limegreen: '#32CD32',
      linen: '#FAF0E6',
      magenta: '#FF00FF',
      maroon: '#800000',
      mediumaquamarine: '#66CDAA',
      mediumblue: '#0000CD',
      mediumorchid: '#BA55D3',
      mediumpurple: '#9370D8',
      mediumseagreen: '#3CB371',
      mediumslateblue: '#7B68EE',
      mediumspringgreen: '#00FA9A',
      mediumturquoise: '#48D1CC',
      mediumvioletred: '#C71585',
      midnightblue: '#191970',
      mintcream: '#F5FFFA',
      mistyrose: '#FFE4E1',
      moccasin: '#FFE4B5',
      navajowhite: '#FFDEAD',
      navy: '#000080',
      oldlace: '#FDF5E6',
      olive: '#808000',
      olivedrab: '#6B8E23',
      orange: '#FFA500',
      orangered: '#FF4500',
      orchid: '#DA70D6',
      palegoldenrod: '#EEE8AA',
      palegreen: '#98FB98',
      paleturquoise: '#AFEEEE',
      palevioletred: '#D87093',
      papayawhip: '#FFEFD5',
      peachpuff: '#FFDAB9',
      peru: '#CD853F',
      pink: '#FFC0CB',
      plum: '#DDA0DD',
      powderblue: '#B0E0E6',
      purple: '#800080',
      rebeccapurple: '#663399',
      red: '#FF0000',
      rosybrown: '#BC8F8F',
      royalblue: '#4169E1',
      saddlebrown: '#8B4513',
      salmon: '#FA8072',
      sandybrown: '#F4A460',
      seagreen: '#2E8B57',
      seashell: '#FFF5EE',
      sienna: '#A0522D',
      silver: '#C0C0C0',
      skyblue: '#87CEEB',
      slateblue: '#6A5ACD',
      slategray: '#708090',
      slategrey: '#708090',
      snow: '#FFFAFA',
      springgreen: '#00FF7F',
      steelblue: '#4682B4',
      tan: '#D2B48C',
      teal: '#008080',
      thistle: '#D8BFD8',
      tomato: '#FF6347',
      turquoise: '#40E0D0',
      violet: '#EE82EE',
      wheat: '#F5DEB3',
      white: '#FFFFFF',
      whitesmoke: '#F5F5F5',
      yellow: '#FFFF00',
      yellowgreen: '#9ACD32'
  };
  var css_integer = '(?:\\+|-)?\\d+';
  var css_float = '(?:\\+|-)?\\d*\\.\\d+';
  var css_number = '(?:' + css_integer + ')|(?:' + css_float + ')';
  css_integer = '(' + css_integer + ')';
  css_float = '(' + css_float + ')';
  css_number = '(' + css_number + ')';
  var css_percentage = css_number + '%';
  var css_whitespace = '\\s*?';
  var hsl_hsla_regex = new RegExp(['^hsl(a?)\\(', css_number, ',', css_percentage, ',', css_percentage, '(,(', css_number, '))?\\)$'].join(css_whitespace));
  var rgb_rgba_integer_regex = new RegExp(['^rgb(a?)\\(', css_integer, ',', css_integer, ',', css_integer, '(,(', css_number, '))?\\)$'].join(css_whitespace));
  var rgb_rgba_percentage_regex = new RegExp(['^rgb(a?)\\(', css_percentage, ',', css_percentage, ',', css_percentage, '(,(', css_number, '))?\\)$'].join(css_whitespace));
  var color;
  var registered_models = [];
  var factories = {};
  if (!this.object) {
      this.object = function(o) {
          function F() {}
          F.prototype = o;
          return new F()
      }
  }
  var object = this.object;
  function pad(val, len) {
      val = val.toString();
      var padded = [];
      for (var i = 0,
      j = Math.max(len - val.length, 0); i < j; i++) {
          padded.push('0')
      }
      padded.push(val);
      return padded.join('')
  }
  function capitalise(s) {
      return s.slice(0, 1).toUpperCase() + s.slice(1)
  }
  function trim(str) {
      return str.replace(/^\s+|\s+$/g, '')
  }
  function cloneOnApply(meth) {
      return function() {
          var cloned = this.clone();
          meth.apply(cloned, arguments);
          return cloned
      }
  }
  function registerModel(name, model) {
      var proto = object(color);
      var fields = [];
      var to_meth = 'to' + capitalise(name);
      function convertAndApply(meth) {
          return function() {
              return meth.apply(this[to_meth](), arguments)
          }
      }
      for (var key in model) if (model.hasOwnProperty(key)) {
          proto[key] = model[key];
          var prop = proto[key];
          if (key.slice(0, 1) == '_') {
              continue
          }
          if (! (key in color) && "function" == typeof prop) {
              color[key] = convertAndApply(prop)
          } else if ("function" != typeof prop) {
              fields.push(key);
              var getter = 'get' + capitalise(key);
              var setter = 'set' + capitalise(key);
              color[getter] = convertAndApply(proto[getter] = (function(key) {
                  return function() {
                      return this[key]
                  }
              })(key));
              color[setter] = convertAndApply(proto[setter] = (function(key) {
                  return function(val) {
                      var cloned = this.clone();
                      cloned[key] = val;
                      return cloned
                  }
              })(key))
          }
      }
      function F() {}
      F.prototype = proto;
      function factory() {
          return new F()
      }
      factories[name] = factory;
      proto.clone = function() {
          var cloned = factory();
          for (var i = 0,
          j = fields.length; i < j; i++) {
              var key = fields[i];
              cloned[key] = this[key]
          }
          return cloned
      };
      color[to_meth] = function() {
          return factory()
      };
      registered_models.push(proto);
      return proto
  }
  color = {
      fromObject: function(o) {
          if (!o) {
              return object(color)
          }
          for (var i = 0,
          j = registered_models.length; i < j; i++) {
              var nu = registered_models[i].fromObject(o);
              if (nu) {
                  return nu
              }
          }
          return object(color)
      },
      toString: function() {
          return this.toCSS()
      }
  };
  var transparent = null;
  registerModel('RGB', {
      red: 0,
      green: 0,
      blue: 0,
      alpha: 0,
      getLuminance: function() {
          return (this.red * 0.2126) + (this.green * 0.7152) + (this.blue * 0.0722)
      },
      blend: function(color, alpha) {
          color = color.toRGB();
          alpha = Math.min(Math.max(alpha, 0), 1);
          var rgb = this.clone();
          rgb.red = (rgb.red * (1 - alpha)) + (color.red * alpha);
          rgb.green = (rgb.green * (1 - alpha)) + (color.green * alpha);
          rgb.blue = (rgb.blue * (1 - alpha)) + (color.blue * alpha);
          rgb.alpha = (rgb.alpha * (1 - alpha)) + (color.alpha * alpha);
          return rgb
      },
      fromObject: function(o) {
          if (o instanceof Array) {
              return this._fromRGBArray(o)
          }
          if ("string" == typeof o) {
              return this._fromCSS(trim(o))
          }
          if (o.hasOwnProperty('red') && o.hasOwnProperty('green') && o.hasOwnProperty('blue')) {
              return this._fromRGB(o)
          }
      },
      _stringParsers: [function(css) {
          css = trim(css);
          var withInteger = match(rgb_rgba_integer_regex, 255);
          if (withInteger) {
              return withInteger
          }
          return match(rgb_rgba_percentage_regex, 100);
          function match(regex, max_value) {
              var colorGroups = css.match(regex);
              if (!colorGroups || ( !! colorGroups[1] + !!colorGroups[5] === 1)) {
                  return null
              }
              var rgb = factories.RGB();
              rgb.red = Math.min(1, Math.max(0, colorGroups[2] / max_value));
              rgb.green = Math.min(1, Math.max(0, colorGroups[3] / max_value));
              rgb.blue = Math.min(1, Math.max(0, colorGroups[4] / max_value));
              rgb.alpha = !!colorGroups[5] ? Math.min(Math.max(parseFloat(colorGroups[6]), 0), 1) : 1;
              return rgb
          }
      },
      function(css) {
          var lower = css.toLowerCase();
          if (lower in css_colors) {
              css = css_colors[lower]
          }
          if (!css.match(/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/)) {
              return
          }
          css = css.replace(/^#/, '');
          var bytes = css.length / 3;
          var max = Math.pow(16, bytes) - 1;
          var rgb = factories.RGB();
          rgb.red = parseInt(css.slice(0, bytes), 16) / max;
          rgb.green = parseInt(css.slice(bytes * 1, bytes * 2), 16) / max;
          rgb.blue = parseInt(css.slice(bytes * 2), 16) / max;
          rgb.alpha = 1;
          return rgb
      },
      function(css) {
          if (css.toLowerCase() !== 'transparent') return;
          return transparent
      }],
      _fromCSS: function(css) {
          var color = null;
          for (var i = 0,
          j = this._stringParsers.length; i < j; i++) {
              color = this._stringParsers[i](css);
              if (color) return color
          }
      },
      _fromRGB: function(RGB) {
          var newRGB = factories.RGB();
          newRGB.red = RGB.red;
          newRGB.green = RGB.green;
          newRGB.blue = RGB.blue;
          newRGB.alpha = RGB.hasOwnProperty('alpha') ? RGB.alpha: 1;
          return newRGB
      },
      _fromRGBArray: function(RGB) {
          var newRGB = factories.RGB();
          newRGB.red = Math.max(0, Math.min(1, RGB[0] / 255));
          newRGB.green = Math.max(0, Math.min(1, RGB[1] / 255));
          newRGB.blue = Math.max(0, Math.min(1, RGB[2] / 255));
          newRGB.alpha = RGB[3] !== undefined ? Math.max(0, Math.min(1, RGB[3])) : 1;
          return newRGB
      },
      toCSSHex: function(bytes) {
          bytes = bytes || 2;
          var max = Math.pow(16, bytes) - 1;
          var css = ["#", pad(Math.round(this.red * max).toString(16).toUpperCase(), bytes), pad(Math.round(this.green * max).toString(16).toUpperCase(), bytes), pad(Math.round(this.blue * max).toString(16).toUpperCase(), bytes)];
          return css.join('')
      },
      toCSS: function(bytes) {
          if (this.alpha === 1) return this.toCSSHex(bytes);
          var max = 255;
          var components = ['rgba(', Math.max(0, Math.min(max, Math.round(this.red * max))), ',', Math.max(0, Math.min(max, Math.round(this.green * max))), ',', Math.max(0, Math.min(max, Math.round(this.blue * max))), ',', Math.max(0, Math.min(1, this.alpha)), ')'];
          return components.join('')
      },
      toHSV: function() {
          var hsv = factories.HSV();
          var min, max, delta;
          min = Math.min(this.red, this.green, this.blue);
          max = Math.max(this.red, this.green, this.blue);
          hsv.value = max;
          delta = max - min;
          if (delta == 0) {
              hsv.hue = hsv.saturation = 0
          } else {
              hsv.saturation = delta / max;
              if (this.red == max) {
                  hsv.hue = (this.green - this.blue) / delta
              } else if (this.green == max) {
                  hsv.hue = 2 + (this.blue - this.red) / delta
              } else {
                  hsv.hue = 4 + (this.red - this.green) / delta
              }
              hsv.hue = ((hsv.hue * 60) + 360) % 360
          }
          hsv.alpha = this.alpha;
          return hsv
      },
      toHSL: function() {
          return this.toHSV().toHSL()
      },
      toRGB: function() {
          return this.clone()
      }
  });
  transparent = color.fromObject({
      red: 0,
      blue: 0,
      green: 0,
      alpha: 0
  });
  registerModel('HSV', {
      hue: 0,
      saturation: 0,
      value: 1,
      alpha: 1,
      shiftHue: cloneOnApply(function(degrees) {
          var hue = (this.hue + degrees) % 360;
          if (hue < 0) {
              hue = (360 + hue) % 360
          }
          this.hue = hue
      }),
      devalueByAmount: cloneOnApply(function(val) {
          this.value = Math.min(1, Math.max(this.value - val, 0))
      }),
      devalueByRatio: cloneOnApply(function(val) {
          this.value = Math.min(1, Math.max(this.value * (1 - val), 0))
      }),
      valueByAmount: cloneOnApply(function(val) {
          this.value = Math.min(1, Math.max(this.value + val, 0))
      }),
      valueByRatio: cloneOnApply(function(val) {
          this.value = Math.min(1, Math.max(this.value * (1 + val), 0))
      }),
      desaturateByAmount: cloneOnApply(function(val) {
          this.saturation = Math.min(1, Math.max(this.saturation - val, 0))
      }),
      desaturateByRatio: cloneOnApply(function(val) {
          this.saturation = Math.min(1, Math.max(this.saturation * (1 - val), 0))
      }),
      saturateByAmount: cloneOnApply(function(val) {
          this.saturation = Math.min(1, Math.max(this.saturation + val, 0))
      }),
      saturateByRatio: cloneOnApply(function(val) {
          this.saturation = Math.min(1, Math.max(this.saturation * (1 + val), 0))
      }),
      schemeFromDegrees: function(degrees) {
          var newColors = [];
          for (var i = 0,
          j = degrees.length; i < j; i++) {
              var col = this.clone();
              col.hue = (this.hue + degrees[i]) % 360;
              newColors.push(col)
          }
          return newColors
      },
      complementaryScheme: function() {
          return this.schemeFromDegrees([0, 180])
      },
      splitComplementaryScheme: function() {
          return this.schemeFromDegrees([0, 150, 320])
      },
      splitComplementaryCWScheme: function() {
          return this.schemeFromDegrees([0, 150, 300])
      },
      splitComplementaryCCWScheme: function() {
          return this.schemeFromDegrees([0, 60, 210])
      },
      triadicScheme: function() {
          return this.schemeFromDegrees([0, 120, 240])
      },
      clashScheme: function() {
          return this.schemeFromDegrees([0, 90, 270])
      },
      tetradicScheme: function() {
          return this.schemeFromDegrees([0, 90, 180, 270])
      },
      fourToneCWScheme: function() {
          return this.schemeFromDegrees([0, 60, 180, 240])
      },
      fourToneCCWScheme: function() {
          return this.schemeFromDegrees([0, 120, 180, 300])
      },
      fiveToneAScheme: function() {
          return this.schemeFromDegrees([0, 115, 155, 205, 245])
      },
      fiveToneBScheme: function() {
          return this.schemeFromDegrees([0, 40, 90, 130, 245])
      },
      fiveToneCScheme: function() {
          return this.schemeFromDegrees([0, 50, 90, 205, 320])
      },
      fiveToneDScheme: function() {
          return this.schemeFromDegrees([0, 40, 155, 270, 310])
      },
      fiveToneEScheme: function() {
          return this.schemeFromDegrees([0, 115, 230, 270, 320])
      },
      sixToneCWScheme: function() {
          return this.schemeFromDegrees([0, 30, 120, 150, 240, 270])
      },
      sixToneCCWScheme: function() {
          return this.schemeFromDegrees([0, 90, 120, 210, 240, 330])
      },
      neutralScheme: function() {
          return this.schemeFromDegrees([0, 15, 30, 45, 60, 75])
      },
      analogousScheme: function() {
          return this.schemeFromDegrees([0, 30, 60, 90, 120, 150])
      },
      fromObject: function(o) {
          if (o.hasOwnProperty('hue') && o.hasOwnProperty('saturation') && o.hasOwnProperty('value')) {
              var hsv = factories.HSV();
              hsv.hue = o.hue;
              hsv.saturation = o.saturation;
              hsv.value = o.value;
              hsv.alpha = o.hasOwnProperty('alpha') ? o.alpha: 1;
              return hsv
          }
          return null
      },
      _normalise: function() {
          this.hue %= 360;
          this.saturation = Math.min(Math.max(0, this.saturation), 1);
          this.value = Math.min(Math.max(0, this.value));
          this.alpha = Math.min(1, Math.max(0, this.alpha))
      },
      toRGB: function() {
          this._normalise();
          var rgb = factories.RGB();
          var i;
          var f, p, q, t;
          if (this.saturation === 0) {
              rgb.red = this.value;
              rgb.green = this.value;
              rgb.blue = this.value;
              rgb.alpha = this.alpha;
              return rgb
          }
          var h = this.hue / 60;
          i = Math.floor(h);
          f = h - i;
          p = this.value * (1 - this.saturation);
          q = this.value * (1 - this.saturation * f);
          t = this.value * (1 - this.saturation * (1 - f));
          switch (i) {
          case 0:
              rgb.red = this.value;
              rgb.green = t;
              rgb.blue = p;
              break;
          case 1:
              rgb.red = q;
              rgb.green = this.value;
              rgb.blue = p;
              break;
          case 2:
              rgb.red = p;
              rgb.green = this.value;
              rgb.blue = t;
              break;
          case 3:
              rgb.red = p;
              rgb.green = q;
              rgb.blue = this.value;
              break;
          case 4:
              rgb.red = t;
              rgb.green = p;
              rgb.blue = this.value;
              break;
          default:
              rgb.red = this.value;
              rgb.green = p;
              rgb.blue = q;
              break
          }
          rgb.alpha = this.alpha;
          return rgb
      },
      toHSL: function() {
          this._normalise();
          var hsl = factories.HSL();
          hsl.hue = this.hue;
          var l = (2 - this.saturation) * this.value,
          s = this.saturation * this.value;
          if (l && 2 - l) {
              s /= (l <= 1) ? l: 2 - l
          }
          l /= 2;
          hsl.saturation = s;
          hsl.lightness = l;
          hsl.alpha = this.alpha;
          return hsl
      },
      toHSV: function() {
          return this.clone()
      }
  });
  registerModel('HSL', {
      hue: 0,
      saturation: 0,
      lightness: 0,
      alpha: 1,
      darkenByAmount: cloneOnApply(function(val) {
          this.lightness = Math.min(1, Math.max(this.lightness - val, 0))
      }),
      darkenByRatio: cloneOnApply(function(val) {
          this.lightness = Math.min(1, Math.max(this.lightness * (1 - val), 0))
      }),
      lightenByAmount: cloneOnApply(function(val) {
          this.lightness = Math.min(1, Math.max(this.lightness + val, 0))
      }),
      lightenByRatio: cloneOnApply(function(val) {
          this.lightness = Math.min(1, Math.max(this.lightness * (1 + val), 0))
      }),
      fromObject: function(o) {
          if ("string" == typeof o) {
              return this._fromCSS(o)
          }
          if (o.hasOwnProperty('hue') && o.hasOwnProperty('saturation') && o.hasOwnProperty('lightness')) {
              return this._fromHSL(o)
          }
      },
      _fromCSS: function(css) {
          var colorGroups = trim(css).match(hsl_hsla_regex);
          if (!colorGroups || ( !! colorGroups[1] + !!colorGroups[5] === 1)) {
              return null
          }
          var hsl = factories.HSL();
          hsl.hue = (colorGroups[2] % 360 + 360) % 360;
          hsl.saturation = Math.max(0, Math.min(parseInt(colorGroups[3], 10) / 100, 1));
          hsl.lightness = Math.max(0, Math.min(parseInt(colorGroups[4], 10) / 100, 1));
          hsl.alpha = !!colorGroups[5] ? Math.max(0, Math.min(1, parseFloat(colorGroups[6]))) : 1;
          return hsl
      },
      _fromHSL: function(HSL) {
          var newHSL = factories.HSL();
          newHSL.hue = HSL.hue;
          newHSL.saturation = HSL.saturation;
          newHSL.lightness = HSL.lightness;
          newHSL.alpha = HSL.hasOwnProperty('alpha') ? HSL.alpha: 1;
          return newHSL
      },
      _normalise: function() {
          this.hue = (this.hue % 360 + 360) % 360;
          this.saturation = Math.min(Math.max(0, this.saturation), 1);
          this.lightness = Math.min(Math.max(0, this.lightness));
          this.alpha = Math.min(1, Math.max(0, this.alpha))
      },
      toHSL: function() {
          return this.clone()
      },
      toHSV: function() {
          this._normalise();
          var hsv = factories.HSV();
          hsv.hue = this.hue;
          var l = 2 * this.lightness,
          s = this.saturation * ((l <= 1) ? l: 2 - l);
          hsv.value = (l + s) / 2;
          hsv.saturation = ((2 * s) / (l + s)) || 0;
          hsv.alpha = this.alpha;
          return hsv
      },
      toRGB: function() {
          return this.toHSV().toRGB()
      }
  });
  function Color(o) {
      return color.fromObject(o)
  }
  Color.isValid = function(str) {
      var key, c = Color(str);
      var length = 0;
      for (key in c) {
          if (c.hasOwnProperty(key)) {
              length++
          }
      }
      return length > 0
  };
  net.brehaut.Color = Color
}).call(net.brehaut);
if (typeof module !== 'undefined') {
  module.exports = net.brehaut.Color
}